package com.im.oauth2.config;

import com.im.oauth2.propertiy.Oauth2ClientProperties;
import com.im.oauth2.propertiy.Oauth2Properties;
import com.im.oauth2.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import java.util.ArrayList;
import java.util.List;

/** @author gongym */
@Configuration
@EnableAuthorizationServer
public class ServerConfig extends AuthorizationServerConfigurerAdapter {
  private Oauth2Properties oAuth2Properties;
  private AuthenticationManager authenticationManager;
  private UserServiceImpl userDetailsService;
  private TokenStore tokenStore;

  private JwtAccessTokenConverter jwtAccessTokenConverter;

  private TokenEnhancer jwtTokenEnhancer;

  private PasswordEncoder passwordEncoder;

  @Autowired
  public ServerConfig(
      Oauth2Properties oAuth2Properties,
      AuthenticationManager authenticationManager,
      UserServiceImpl userDetailsService,
      @Qualifier("jwtTokenStore") TokenStore tokenStore,
      JwtAccessTokenConverter jwtAccessTokenConverter,
      TokenEnhancer jwtTokenEnhancer,
      PasswordEncoder passwordEncoder) {
    this.oAuth2Properties = oAuth2Properties;
    this.authenticationManager = authenticationManager;
    this.userDetailsService = userDetailsService;
    this.tokenStore = tokenStore;
    this.jwtAccessTokenConverter = jwtAccessTokenConverter;
    this.jwtTokenEnhancer = jwtTokenEnhancer;
    this.passwordEncoder = passwordEncoder;
  }

  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
    endpoints
        .tokenStore(tokenStore)
        .authenticationManager(authenticationManager)
        .userDetailsService(userDetailsService);
    // 扩展token返回结果
    if (jwtAccessTokenConverter != null && jwtTokenEnhancer != null) {
      TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
      List<TokenEnhancer> enhancerList = new ArrayList<>();
      enhancerList.add(jwtTokenEnhancer);
      enhancerList.add(jwtAccessTokenConverter);
      tokenEnhancerChain.setTokenEnhancers(enhancerList);
      // jwt
      endpoints.tokenEnhancer(tokenEnhancerChain).accessTokenConverter(jwtAccessTokenConverter);
    }
  }
  /** 配置客户端一些信息 */
  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    InMemoryClientDetailsServiceBuilder build = clients.inMemory();
    if (oAuth2Properties.getClients().length > 0) {
      for (Oauth2ClientProperties config : oAuth2Properties.getClients()) {
        build
            .withClient(config.getClientId())
            .secret(passwordEncoder.encode(config.getClientSecret()))
            .accessTokenValiditySeconds(config.getAccessTokenValiditySeconds())
            .refreshTokenValiditySeconds(60 * 60 * 24 * 15)
            .authorizedGrantTypes("refresh_token", "password", "authorization_code")
            .scopes("all");
      }
    }
  }
  /** springSecurity 授权表达式， */
  @Override
  public void configure(AuthorizationServerSecurityConfigurer security) {
    security.tokenKeyAccess("permitAll()");
    security.checkTokenAccess("isAuthenticated()");
  }
}
